package com.dxg.provider;

import com.dxg.provider.token.SmsAuthenticationToken;
import javax.annotation.Resource;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

/**
 * @author dingxigui
 * @version 1.0
 * @date 2021/7/30 16:11
 */
@Component
public class SmsAuthenticationProvider extends CustomerAbstractAuthenticationProvider{

  @Resource
  private UserDetailsService smsUserDetailService;

  @Resource
  private PasswordEncoder passwordEncoder;

  @Override
  protected UserDetails retrieveUser(String username, Authentication authentication)
      throws AuthenticationException {
    try {
      UserDetails loadedUser = this.getSmsUserDetailService().loadUserByUsername(username);
      if (loadedUser == null) {
        throw new InternalAuthenticationServiceException(
            "UserDetailsService returned null, which is an interface contract violation");
      }
      return loadedUser;
    }
    catch (Exception ex) {
      throw new InternalAuthenticationServiceException(ex.getMessage(), ex);
    }
  }

  @Override
  protected void additionalAuthenticationChecks(UserDetails userDetails,
      Authentication authentication) throws AuthenticationException {
    if (authentication.getCredentials() == null) {
      logger.debug("密码不为为空");

      throw new BadCredentialsException(messages.getMessage(
          "AbstractUserDetailsAuthenticationProvider.badCredentials",
          "Bad credentials"));
    }

    String presentedPassword = authentication.getCredentials().toString();

    if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
      logger.debug("密码匹配失败");

      throw new BadCredentialsException(messages.getMessage(
          "AbstractUserDetailsAuthenticationProvider.badCredentials",
          "Bad credentials"));
    }
  }


  @Override
  protected void doAfterPropertiesSet() throws Exception {
    Assert.notNull(this.smsUserDetailService, "SmsAuthenticationProvider的UserDetailsService必须设置");
    Assert.notNull(this.passwordEncoder, "SmsAuthenticationProvider的passwordEncoder必须设置");

  }

  /**
   * 短信认证令牌才进行校验
   * @param authentication
   * @return
   */
  @Override
  public boolean supports(Class<?> authentication) {
    return (SmsAuthenticationToken.class.isAssignableFrom(authentication));
  }

  public UserDetailsService getSmsUserDetailService() {
    return smsUserDetailService;
  }

  public void setSmsUserDetailService(
      UserDetailsService smsUserDetailService) {
    this.smsUserDetailService = smsUserDetailService;
  }

  public PasswordEncoder getPasswordEncoder() {
    return passwordEncoder;
  }

  public void setPasswordEncoder(
      PasswordEncoder passwordEncoder) {
    this.passwordEncoder = passwordEncoder;
  }
}
